﻿using System;
using System.Configuration;
using System.IO;
using System.Reflection;

using Gonte.Collections;
using Gonte.Reflection;
using System.Collections.Generic;

namespace Gonte.Plugin
{
    /// <summary>
    /// Loads and retrieves the plugins
    /// </summary>
    public static class PluginManager
    {
        /// <summary>
        /// Loads all the plugins
        /// </summary>
        static PluginManager()
        {
            plugins_ = new Dictionary<string, Dictionary<string, Type>>();
            string path;

            PluginConfigurationSection pluginSection = (PluginConfigurationSection)ConfigurationManager.GetSection(PluginConfigurationSection.PluginConfigurationSectionString);
            if (pluginSection != null)
            {
                path = pluginSection.PluginsDirectory;
            }
            else
            {
                path = Path.Combine(Environment.CurrentDirectory, "Plugins");
            }

            foreach (string file in Directory.GetFiles(path, "*.dll"))
            {
                Assembly assembly = Assembly.LoadFrom(file);

                foreach (Type type in assembly.GetTypes())
                {
                    PluginAttribute attribute = CustomAttribute.GetCustomAttribute<PluginAttribute>(type, false);

                    if (attribute != null)
                    {
                        string category = attribute.Category;
                        if (!plugins_.ContainsKey(category))
                        {
                            plugins_[category] = new Dictionary<string, Type>();
                        }
                        plugins_[category][attribute.Name] = type;
                    }
                }
            }
        }

        /// <summary>
        /// Retrieves the plugin with the given category and name
        /// </summary>
        /// <param name="category">The category or group the plugin belongs to</param>
        /// <param name="name">The plugin name</param>
        /// <returns>The plugin</returns>
        public static Object GetPlugin(string category, string name)
        {
            if (string.IsNullOrEmpty(category))
            {
                throw new ArgumentNullException("Category");
            }

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("Name");
            }

            Type type = plugins_[category][name];
            return Activator.CreateInstance(type);
        }

        private static Dictionary<string, Dictionary<string, Type>> plugins_;
    }
}
